package h5

import (
	"chess_platform/internal/alisdk"
	. "chess_platform/internal/common"
	"chess_platform/internal/login"
	"chess_platform/internal/token"
	"chess_platform/models/client"
	"chess_platform/models/h5"
	"encoding/json"
	"fmt"
	"time"
)

//[h5]登录
type LoginController struct {
	BaseController
}

func (b *LoginController) URLMapping() {
	b.Mapping("Login", b.Login)
	b.Mapping("WeChatLogin", b.WeChatLogin)
	b.Mapping("ResetPassword", b.ResetPassword)
	b.Mapping("Captcha", b.Captcha)
	b.Mapping("Test", b.Test)
	b.Mapping("Share", b.Share)
}

// @Title 分享
// @Description 分享
// @Param   uri        body    string  true      "当前网页uri,除去#号后面的"
// @Success 0 {string} 状态码
// @Failure 400
// @Failure 404
// @router /share [post]
func (b *LoginController) Share() {
	type Params struct {
		Uri string `json:"uri" valid:"Required"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}
	sign, err := login.GetWeChatTicket(p.Uri)
	if err != nil {
		LogH5.Error(b.SystemError(err.Error()))

		return
	}
	b.Res.Data = sign
	b.ResponseSuccess()
}

// @Title 发送短信验证码
// @Description 发送短信验证码
// @Param   phone     body    string  true      "手机号"
// @Param   check     body    int     true      "是否需要检验手机号存在于数据库,0-不需求,1-需要"
// @Success 0 {string} captcha 验证码
// @Failure 400
// @Failure 404
// @router /captcha [post]
func (b *LoginController) Captcha() {
	type Params struct {
		Phone string `json:"phone"`
		Check int64  `json:"check" valid:"Range(0,1)"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	b.Valid.Required(p.Phone, "phone").Message("手机号不能为空")
	b.Valid.Phone(p.Phone, "phone").Message("错误的手机号")
	if !b.ValidParams(&p) {
		return
	}
	if p.Check == 1 {
		uid, err := h5.IsUserExistByPhone(p.Phone)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}
		if uid == 0 {
			b.Res.Code = ErrNotFound
			b.Res.Msg = MsgErrUserNotFound
			b.Response()
			return
		}
	}

	captcha, msg, err := alisdk.SendSMSCaptcha(p.Phone, Sms.SmsSignName, Sms.SmsCode, KeyH5Phone,
		MemCache, CaptchaCacheExpire, CaptchaSendAgainExpire)
	if err != nil {
		LogH5.Error(b.SystemError(err.Error()))
		return
	}
	if msg != "OK" {
		b.ResponseFail(msg)
		return
	}
	LogH5.Debug(fmt.Sprintf("发送到手机:%v,验证码:%v", p.Phone, captcha))
	b.Res.Code = Success
	b.Res.Msg = MsgSuccess
	b.Response()
}

// @Title 忘记密码而重置密码
// @Description 忘记密码而重置密码
// @Param   phone         body    string  true      "手机号"
// @Param   new_password  body    string  true      "新密码"
// @Param   captcha       body    string  true      "短信验证码"
// @Success 0 {string} 状态码
// @Failure 400
// @Failure 404
// @router /reset-password [post]
func (b *LoginController) ResetPassword() {
	type Params struct {
		Phone       string `json:"phone"`
		NewPassword string `json:"new_password"`
		Captcha     string `json:"captcha"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	b.Valid.Required(p.Phone, "phone").Message("手机号不能为空")
	b.Valid.Phone(p.Phone, "phone").Message("错误的手机号")
	b.Valid.MinSize(p.NewPassword, 6, "new_password").Message("密码长度为6-15个字符")
	b.Valid.MaxSize(p.NewPassword, 15, "new_password").Message("密码长度为6-15个字符")
	b.Valid.Required(p.Captcha, "captcha").Message("验证码不能为空")
	b.Valid.Numeric(p.Captcha, "captcha").Message("验证码为6位数字")
	b.Valid.Length(p.Captcha, 6, "captcha").Message("验证码为6位数字")
	if !b.VerifyParamsError() {
		return
	}
	err, ok := alisdk.VerifySMSCaptcha(p.Phone, p.Captcha, KeyH5Phone, MemCache)
	if !ok {
		b.Res.Code = ErrCaptchaVerify
		b.Res.Msg = err.Error()
		b.Response()
		LogH5.Notice(err.Error())
		return
	}

	uid, err := h5.IsUserExistByPhone(p.Phone)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if uid == 0 {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrUserNotFound
		b.Response()
		return
	}

	user := map[string]interface{}{
		"password": Md5sum(p.NewPassword),
	}
	_, err = h5.UpdateUser(user, uid)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))

		return
	}
	b.ResponseSuccess()
}

// @Title 手机登录
// @Description 手机登录
// @Param   telephone     body    string  true      "手机号用于登录"
// @Param   password  	  body    string  true      "密码"
// @Success 0 {string} token 字符串
// @Failure 400
// @Failure 404
// @router /login [post]
func (b *LoginController) Login() {
	if !b.IsServerStop() {
		return
	}
	type Params struct {
		Phone    string
		Password string
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	b.Valid.Required(p.Phone, "phone").Message("手机号不能为空")
	b.Valid.Phone(p.Phone, "phone").Message("错误的手机号")
	b.Valid.Required(p.Password, "password").Message("密码不能为空")
	b.Valid.MinSize(p.Password, 6, "password").Message("密码长度为6-15个字符")
	b.Valid.MaxSize(p.Password, 15, "password").Message("密码长度为6-15个字符")
	if !b.VerifyParamsError() {
		return
	}

	dbUser, err := h5.UserInfoByTelephone(p.Phone)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}

	if dbUser == nil || dbUser.Password != Md5sum(p.Password) {
		b.Res.Code = ErrUserOrPassword
		b.Res.Msg = MsgErrPhoneOrPassword
		b.Response()
		return
	}
	if dbUser.Frozen == 1 { //被冻结了
		b.ResponseFail(fmt.Sprintf("您已被冻结,请联系客服,冻结理由:%v", dbUser.FrozenReason))
		return
	}

	//判断用户是否今天首次登录
	var firstTime int
	if !IsToday(dbUser.LoginTime) {
		firstTime = 1
	}

	tokenStr := token.Create(dbUser.Uid, dbUser.Level, TokenH5, dbUser.Status)
	data := map[string]interface{}{
		"status":        dbUser.Status, //登录返回状态
		"level":         dbUser.Level,
		"initial_login": firstTime, //今天第一次登录
	}
	key := fmt.Sprintf("%v%v", KeyH5TokenCache, dbUser.Uid)
	RedisCache.Put(key, tokenStr, time.Duration(Secret.H5TokenCacheExpire)*time.Second)
	b.Res.Code = Success
	b.Res.Msg = MsgLoginSuccess
	b.Res.Data = data
	b.Res.Token = tokenStr
	b.Response()
	user := map[string]interface{}{
		"login_type": 2, //1-微信登录,2-手机登录
		"login_time": time.Now().Unix(),
	}
	h5.UpdateUser(user, dbUser.Uid)

	log := map[string]interface{}{
		"login_time": time.Now().Unix(),
		"uid":        dbUser.Uid,
		"ip":         b.Ctx.Input.IP(),
		"login_type": 2, //1-微信登录,2-手机登录
	}
	h5.NewLoginLog(log)
}

// @Title 微信登录
// @Description 微信登录
// @Param   code       body    string  true      "微信用户code"
// @Param   pid        body    int     false     "一级代理的id(扫二维码成为二级代理)"
// @Success 0 {string} token
// @Failure 400
// @Failure 404
// @router /weChat-login [post]
func (b *LoginController) WeChatLogin() {
	if !b.IsServerStop() {
		return
	}

	type Params struct {
		Code string `json:"code" valid:"Required"`
		Pid  int64  `json:"pid"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.VerifyParamsError() {
		return
	}

	t, err := login.GetWeChatOpenIdAccessToken(p.Code)
	if err != nil {
		LogH5.Error(b.SystemError(err.Error()))
		return
	}
	if t.AccessToken == "" || t.OpenId == "" {
		LogH5.Error(b.LoginRetry(fmt.Sprintf("无效的open_id:%v\naccess_token:%v\n", t.OpenId, t.AccessToken)))
		return
	}

	weChat, err := login.GetWeChatUserInfo(t.AccessToken, t.OpenId)
	if err != nil {
		LogH5.Error(b.LoginRetry(err.Error()))
		return
	}
	if weChat == nil {
		LogH5.Error(b.LoginRetry(err.Error()))
		return
	}

	user := map[string]interface{}{
		"union_id":     weChat.UnionID,
		"open_id":      weChat.OpenID,
		"login_type":   1, //1-微信登录,2-手机登录
		"nickname":     FilterEmoji(weChat.NickName),
		"sex":          weChat.Sex,
		"province":     weChat.Province,
		"city":         weChat.City,
		"head_img_url": weChat.HeadImgURL,
		"login_time":   time.Now().Unix(),
	}

	u, err := h5.IsUserExistByOpenID(t.OpenId)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}

	var Uid int64 //代理的id

	if u != nil { //exist, update user info
		Uid = u.Uid

		if u.Frozen == 1 { //被冻结了
			b.ResponseFail(fmt.Sprintf("您已被冻结,请联系客服,冻结理由:%v", u.FrozenReason))
			return
		}

		_, err := h5.UpdateUser(user, u.Uid)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}

		//判断用户是否今天首次登录
		var firstTime int
		if !IsToday(u.LoginTime) {
			firstTime = 1
		}

		tokenStr := token.Create(u.Uid, u.Level, TokenH5, u.Status)
		key := fmt.Sprintf("%v%v", KeyH5TokenCache, u.Uid)
		RedisCache.Put(key, tokenStr, time.Duration(Secret.H5TokenCacheExpire)*time.Second)
		data := map[string]interface{}{
			"status":        u.Status, //登录返回状态
			"level":         u.Level,
			"initial_login": firstTime, //今天第一次登录
		}

		b.Res.Code = Success
		b.Res.Msg = MsgLoginSuccess
		b.Res.Data = data
		b.Res.Token = tokenStr
		b.Response()
	} else { //doesn't exist, add a new user
		var level int64 = 1
		uid := client.GetNormalAgentUid()
		if uid == 0 {
			LogH5.Error(b.SystemError(fmt.Sprintf("获取代理ID失败,可能代理ID已经使用完毕")))
			return
		}
		Uid = uid

		user["create_time"] = time.Now().Unix()
		user["uid"] = uid
		status := RegisterSuccess
		returnData := map[string]interface{}{
			"status":        status,
			"initial_login": 1,
		}
		o := NewDBOrm(DBChessCenter)
		o.Begin()
		defer o.Rollback()
		if p.Pid != 0 {
			//获取一级代理的名额
			field := []string{"agent_num", "group_id"}
			u, err := h5.SpecifyUserInfoById(p.Pid, field, o)
			if err != nil {
				o.Rollback()
				LogH5.Error(b.DatabaseError(err.Error()))
				return
			}
			if u == nil {
				o.Rollback()
				LogH5.Error(fmt.Sprintf("注册失败,邀请者(代理)不存在,请联系者提供正确的二维码,h5_user表里没有找到一级代理:%d", p.Pid))
				b.ResponseFail("注册失败,邀请者(代理)不存在,请联系者提供正确的二维码")
				return
			}
			//代理名额不足
			if u.AgentNum < 1 {
				o.Rollback()
				b.Res.Code = ErrAgentNumNotEnough
				b.Res.Msg = MsgErrAgentNumNotEnough
				b.Response()
				return
			}
			//减少代理的名额
			n, err := h5.UpdateUserAgentNum(-1, p.Pid, o)
			if err != nil || n == 0 {
				o.Rollback()
				LogH5.Error(b.DatabaseError(err.Error()))
				return
			}
			user["group_id"] = u.GroupId
			user["level"] = Level2
			user["pid"] = p.Pid
			status = AuthCodeSuccess
			user["status"] = status
			returnData["status"] = status //输入授权码成功,下一步绑定手机
			returnData["level"] = Level2
			level = Level2
		}
		_, err = h5.NewUser(user, o)
		if err != nil {
			o.Rollback()
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}
		o.Commit()

		tokenStr := token.Create(uid, level, TokenH5, status)
		key := fmt.Sprintf("%v%v", KeyH5TokenCache, uid)
		RedisCache.Put(key, tokenStr, time.Duration(Secret.H5TokenCacheExpire)*time.Second)
		b.Res.Code = Success
		b.Res.Msg = MsgLoginSuccess
		b.Res.Data = returnData
		b.Res.Token = tokenStr
		b.Response()
	}

	log := map[string]interface{}{
		"login_time": time.Now().Unix(),
		"uid":        Uid,
		"ip":         b.Ctx.Input.IP(),
		"login_type": 1, //1-微信登录,2-手机登录
	}
	h5.NewLoginLog(log)

}

// @Title 代码测试
// @Description 代码测试
// @Success 0 {string} token
// @Failure 400
// @Failure 404
// @router /test [get]
func (b *LoginController) Test() {
	if !b.IsDevelopMode() {
		return
	}
	type Params struct {
		Content string `json:"content"`
		Time    int64  `json:"time"`
	}
	var p Params
	p.Content = "这是一个推送的跑马灯,给我播3次"
	p.Time = 3
	horseMsg, err := json.Marshal(p)
	if err != nil {
		b.ResponseFail(err.Error())
	}
	//time.Sleep(10 * time.Second)
	fmt.Println("-----------------horseMsg:", string(horseMsg))
	if !client.BroadCastMsgToLobby(0, GenBroadcastMsg(ModuleHorse, ActionNewHorse, p)) {
		b.ResponseFail()
	}
	user, _ := client.QueryUserInfoById(317021)

	//horse, _ := client.ListHorse(1)
	//role, _ := pc.RoleAuthorizedInfo(5)
	b.Res.Data = map[string]interface{}{
		//"role":       role,
		//"permission": pc.SimplifyPermission(role),
		//	"horse":      horse,
		"user": user,
	}
	b.ResponseSuccess()

}
